<?php

/**
 * Description of Manager
 *
 * @author Francis Adu-Gyamfi
 */
abstract class Manager extends Controller {
    
    private $itemsTable = NULL;
    private $categoriesTable = NULL;
    private $categoryField = "CategoryID";
    
    private $itemClassName = NULL;
    private $categoryClassName = NULL;
    
    /**
     * The name of the field to indicate a model is published or active
     * @var string 
     */
    protected $publishField = "Published";
    
    /**
     * The Controller constructor
     */
    public function __construct($itemsTable = NULL, $categoriesTable = NULL) {
        
        parent::__construct();

        $this->setItemsTable($itemsTable);
        $this->setCategoriesTable($categoriesTable);
    }

    public function setItemsTable($itemsTable) {
        $this->itemsTable = $itemsTable;
    }

    public function getItemsTable() {
        return $this->itemsTable;
    }

    public function setItemClassName($itemClassName) {
        $this->itemClassName = $itemClassName;
    }

    public function getItemClassName() {
        return $this->itemClassName;
    }

    public function setCategoriesTable($categoriesTable) {
        return $this->categoriesTable = $categoriesTable;
    }

    public function getCategoriesTable() {
        return $this->categoriesTable;
    }

    public function getCategoryClassName() {
        return $this->categoryClassName;
    }

    public function setCategoryClassName($categoryClassName) {
        $this->categoryClassName = $categoryClassName;
    }
    
    /**
     * Returns an Item from the database based on the parameter supplied.
     * If the parameter is an array, the Controller::find() method would be invoked
     * with the Item ClassName and the array parameter would be used as the options.
     *
     * If the parameter is supplied is a simple int, then it is assumed to be a primary key
     * so it will be used to create an instance of the Item object and that will be returned
     * instantly, deferring the database query for data when data is actually request via
     * the Model::getData() method
     *
     * The function is expected to return only one item, so if multiple items are found
     * via the options passed (if array) only the first item in the list will be returned
     *
     * @param mixed $data an int or array of options
     * @return Model an instance of a Model based on the ItemClassName
     */
    public function getItem($data) {

        if( is_array($data) ) {
            $options = $data;
            $items = $this->find( $this->getItemClassName(), $options );

            return count($items) >= 1 ? $items[0] : NULL;
        }

        if (is_int(intval($data)) <= 0) {
            trigger_error("Supplied Value Is Not A Valid ID");
            return;
        }

        if( !$this->isValidClassName($this->getItemClassName()) ) {
            return NULL;
        }

        $obj = new $this->itemClassName($data);

        return $obj;
    }

    /**
     * Returns an array of items from the database starting from the specified index
     * 
     * @param int $start
     * @param int $limit
     * @param array $options
     * @return array 
     */
    public function getItems($start = 0, $limit = NULL, $options = NULL) {

        $pageFilter = array(
            'offset' => $start,
            'limit' => $limit
        );

        $options = array_merge($pageFilter, $options ? $options : array());

        return $this->find($this->getItemClassName(), $options);

    }

    /**
     * Returns the total number of Items in the database
     * 
     * @param array $options
     * @return int
     */
    public function getTotalItemCount($options = NULL) { 
		return $this->count($this->getItemClassName(), $options);
    }

    /**
     * Returns the Category instance with the specified ID
     * 
     * @param int $id
     * @return Model
     */
    public function getCategory($id) {
        if (is_int(intval($id)) <= 0) {
            trigger_error("Supplied Value Is Not A Valid ID");
            return NULL;
        }

        if( !$this->isValidClassName($this->categoryClassName) ) {
            return NULL;
        }

        $obj = new $this->categoryClassName($id);

        return $obj;
    }

    /**
     * Returns an array of Models that represent the category
     * 
     * @param array $options
     * @return array
     */
    public function getCategories($options = NULL) {

        if( !$this->isValidClassName($this->getCategoryClassName()) ) {
            return array();
        }

        return $this->find( $this->getCategoryClassName(), $options);
    }

    /**
     * Deletes the articles with the specified ID or IDs from the database
     *
     * @param array $ids the ID or IDs to delete, can be an array or an int
     */
    public function deleteItems($ids) {
        if (!defined("IN_CMS") || !IN_CMS || $this->itemsTable == NULL) {
            return;
        }

        if (!is_array($ids) && !is_int($ids)) {
            die("Invalid Parameter Passed In " . __FILE__ . " On Line " . __LINE__ . " To Method " . __METHOD__);
        }
        
        if( is_int($id) ) {
            $id = array($id);
        }

        $query = sprintf("DELETE FROM {$this->getItemsTable()} WHERE id IN (%s) ", implode(",", $ids));

        $db = $this->getDatabase();
        $db->query($query, true);
    }

    /**
     * Deletes an item from the database based on the id supplied
     *
     * @param int $id the item id
     * @return bool returns true if the delete completed without errors
     */
    public function deleteItem($id) {
        if( is_int($id) ) {
            return $this->deleteItems(array($id));
        }
    }

    /**
     * Deletes Categories from the specified Categories Table
     * 
     * @param array $category_ids the IDs of the categories to delete
     * @return bool returns true of the delete completeed without errors
     */
    public function deleteCategories($category_ids) {
        if (!defined("IN_CMS") || !IN_CMS) {
            return false;
        }

        $db = $this->getDatabase();

        $deleteSQL = sprintf("DELETE FROM {$this->getCategoriesTable()} WHERE id IN (%s) ", implode(",", $category_ids));

        $db->query($deleteSQL, true);

        return $db->getError() == "";
    }

    /**
     * Deletes the category with the specified ID from the database
     * 
     * @param int $category_id the id of the category to delete
     * @return bool returns true if the delete completes without error, false otherwise
     */
    public function deleteCategory($category_id) {
        return $this->deleteCategories(array($category_id));
    }

    /**
     * Publishes the specified item
     * 
     * @param int $id
     * @param bool $publish
     */
    public function publishItem($id, $publish = true) {
        if (!defined("IN_CMS") || !IN_CMS) {
            return;
        }

        $db = $this->getDatabase();

        $updateSQL = sprintf("UPDATE {$this->getItemsTable()} SET {$this->publishField} = %s WHERE id = %s",
                $db->sanitizeInput($publish ? 1 : 0, 'int'),
                $db->sanitizeInput($id, 'int'));

        echo $updateSQL;

        $db->query($updateSQL, true);
    }

    /**
     * Moves the specified items to a new category
     * 
     * @param array $ids
     * @param int $category_id
     * @return bool
     */
    public function moveItems($ids, $category_id) {
        if (!defined("IN_CMS") || !IN_CMS) {
            return false;
        }

        if (!is_array($ids) && !is_int($ids)) {
            die("Invalid Parameter Passed In " . __FILE__ . " On Line " . __LINE__ . " To Method " . __METHOD__);
        }

        $db = $this->getDatabase();
        $query = sprintf("UPDATE {$this->getItemsTable()} SET {$this->categoryField} = %s WHERE id IN (%s)",
                $db->sanitizeInput($category_id, 'int'),
                implode(",", $ids)
        );

        echo $query;

        $db->query($query, true);

        return $db->getError() == "";
    }
}

?>
